import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;

public class ChatRoomServer {
    private final LinkedList<Socket> online;

    public ChatRoomServer() {
        this.online = new LinkedList<>();
    }

    public static void main(String[] args) {
        ChatRoomServer server = new ChatRoomServer();

        try (ServerSocket serverSocket = new ServerSocket(18989)) {
            while (true) {
                // 接收连接
                Socket socket = serverSocket.accept();
                server.online.add(socket);

                server.new MessageDispatcher(socket).start(); // 启动线程
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    class MessageDispatcher extends Thread {
        private final Socket socket;
        private final String userName;

        public MessageDispatcher(Socket socket) {
            this.socket = socket;

            String ip = socket.getInetAddress().getHostAddress();
            this.userName = String.format("来自%s的网u", ip);
        }

        @Override
        public void run() {
            try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
                dispatch(userName + "上线了！");
                String message;
                while ((message = bufferedReader.readLine()) != null) {
                    dispatch(userName + "说：" + message);
                }

                dispatch(userName + "下线了！");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        /**
         * 向所有在线的用户转发消息，包括发送消息的人
         *
         * @param message 需要转发的消息
         */
        private void dispatch(String message) throws IOException {
            for (Socket on : online) {
                try (PrintStream ps = new PrintStream(on.getOutputStream())) {
                    ps.println(message);
                }
            }
        }
    }
}
